/*
#Copyright (c) 2013, Philippe Bordron <philippe.bordron@gmail.com>
#
# This file is part of SIPPER.
#
# DCC is free software: you can redistribute it and/or modify
# it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# DCC is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU LESSER GENERAL PUBLIC LICENSE for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# along with SIPPER.  If not, see <http://www.gnu.org/licenses/>
*/
package combi.wip.graph.algo.ksp;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

import combi.wip.graph.algo.ksp.Ksp_Yen;
import combi.wip.graph.algo.ksp.LabelGroupeSommets;

import org.jgrapht.graph.DefaultDirectedWeightedGraph;
import org.jgrapht.graph.DefaultWeightedEdge;
import org.jgrapht.graph.DirectedMaskSubgraph;

import combi.graph.Mask;

public class TraiteDebutChemins extends Thread {

	ControleCheminsEnParallele controle;
	Set<Integer> entry1;
	Collection<Set<Integer>> finElem;
	String labelDeb;
	LabelGroupeSommets<Set<Integer>> labels;
	DefaultDirectedWeightedGraph<Integer, DefaultWeightedEdge> graph;
	Mask<Integer, DefaultWeightedEdge> maskBase;
	int fakeSrc;
	int fakeDest;
	int k;
	String outFile;
	
	Mask<Integer, DefaultWeightedEdge> mask;
	DirectedMaskSubgraph<Integer, DefaultWeightedEdge> mod;

	public TraiteDebutChemins(ControleCheminsEnParallele root,
			int nb_threads,
			DefaultDirectedWeightedGraph<Integer, DefaultWeightedEdge> graph,
			Mask<Integer, DefaultWeightedEdge> mask,
			int fakeSrc,
			int fakeDest,
			int k,Set<Integer> deb,
			Collection<Set<Integer>> finElem,  String labelDeb,
			LabelGroupeSommets<Set<Integer>> labels,
			String outFile)
	{
		//super(nb_threads);
		this.controle = root;
		this.fakeSrc = fakeSrc;
		this.fakeDest = fakeDest;
		this.entry1 = deb;
		this.finElem = finElem;
		this.labelDeb = labelDeb;
		this.labels = labels;
		this.outFile = outFile;
		this.graph = graph;
		this.maskBase = mask;
		this.k = k;
	}


	public void run()
	{
		calcul();
		controle.remove();
	}
	
	public void calcul()
	{
		BufferedWriter out;
		mask = new Mask<Integer, DefaultWeightedEdge>(maskBase);
		mod = new DirectedMaskSubgraph<Integer, DefaultWeightedEdge>(graph, mask);

		for (Integer v : entry1)
		{
			mask.removeEdge(graph.getEdge(fakeSrc,v)); // retrait des arcs masquants
		}
		for (Set<Integer> entry2 : finElem)
		{
			if (!entry1.equals(entry2))
			{

				for (Integer w : entry2)
				{
					mask.removeEdge(graph.getEdge(w, fakeDest));
				}
				Ksp_Yen<Integer, DefaultWeightedEdge> algo = new Ksp_Yen<Integer, DefaultWeightedEdge>(mod, fakeSrc, fakeDest, k);
				Thread t = new Thread(algo);
				t.start();
				try {
					t.join();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				String labelFin = entry2.toString();
				if (labels != null)
				{
					//debut = labels.getLabel(entry1);
					labelFin = labels.getLabel(entry2);
				}
				synchronized(this)
				{
					try {
						out = new BufferedWriter(new FileWriter(outFile, true));
					
					out.write(labelDeb + "->" + labelFin + "\n");
					for(List<DefaultWeightedEdge> l : algo.getPaths())
					{
						if (algo.getScoreChemin(l) == 0)
						{
							System.err.println(l);
						}
						out.write(algo.getScoreChemin(l) + "\t" + (l.size() - 1) +"\t"+algo.convertEdgesPath2NodesPath(cut(l))+"\n");
					}
					out.write("\n");
					out.close();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					for (Integer w : entry2)
					{
						mask.addEdge(graph.getEdge(w, fakeDest));
					}
					
				}
			}
		}
		mask.clear();
		/*for (Integer v : entry1)
		{
			mask.addEdge(graph.getEdge(fakeSrc,v));
		}*/
	}
	

	private static List<DefaultWeightedEdge> cut (List<DefaultWeightedEdge> l)
	{
		l.remove(l.size()-1);
		l.remove(0);
		return l;
	}
	
}
